#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/12/10 10:43
# @Author  : XH
# @File    : http_base.py
# @Software: PyCharm
import base64
import json
import os
from dataclasses import dataclass, field
from typing import Dict, Optional, Any, Union
from urllib.parse import urlencode

import requests
from dotenv import load_dotenv
from requests.auth import HTTPBasicAuth

from api.get_token import get_cookie
from common.handle_log import mylog
from common.handle_yaml import HandleYaml


@dataclass
class Request:
    method: str = None  # 默认请求方法
    # 每次创建类的实例时，都会重新生成一个新的空字典。不会有多个实例共享同一个字典，避免了潜在的错误;标明请求头一定是个字典
    headers: Dict[str, str] = field(default_factory=dict)
    host: str = None  # 主机地址
    path: str = None  # 请求路径
    data: Optional[Dict[str, Any]] = None  # 请求体数据
    query: Optional[Dict[str, Any]] = None  # 查询参数
    type: str = "json"  # 请求体格式，默认为 JSON
    timeout: int = 30  # 请求超时时间（秒）
    auth: Optional[HTTPBasicAuth] = None  # 认证信息
    cookie:Optional[Dict[str,str]] = None
    proxies: Optional[Dict[str, str]] = None  # 代理
    allow_redirects: bool = True  # 是否允许重定向
    verify: bool = False

    def load_access_token(self):
        """加载并设置 ACCESS_TOKEN 到请求头"""
        access_token = self._get_access_token_from_env()
        if access_token:
            self.headers["Authorization"] = access_token
            mylog.info("Token successfully loaded into headers.")
        else:
            mylog.warning("ACCESS_TOKEN environment variable not set, unable to load to headers. ")

    def _get_access_token_from_env(self) -> Optional[str]:
        """从环境变量中获取 ACCESS_TOKEN"""
        load_dotenv()
        ACCESS_TOKEN = os.getenv('ACCESS_TOKEN')

        return ACCESS_TOKEN  # Assuming ACCESS_TOKEN is globally available

    def load_cookie(self) -> dict:
        """获取 Cookie"""
        return get_cookie()

    def load_environment(self) -> str:
        """加载配置环境并返回 host 地址"""
        env = HandleYaml("env_config.yaml").read_yaml()
        return env["env"].get("test", "default_host")  # 默认值可以根据需要设置

    def prepare_data(self):
        """根据请求类型设置 Content-Type 和处理数据"""
        if self.type == "json":
            self.headers["Content-Type"] = "application/json"
            if self.data:
                self.data = json.dumps(self.data)
        elif self.type == "xml":
            self.headers["Content-Type"] = "application/xml"
        elif self.type == "text":
            self.headers["Content-Type"] = "text/plain"
            if self.data:
                self.data = str(self.data)  # 将数据转换为字符串
        elif self.type == "form":
            self.headers["Content-Type"] = "application/x-www-form-urlencoded"
            if self.data:
                self.data = urlencode(self.data)
        else:
            raise ValueError(f"Unsupported request type: {self.type}")

    def debug_log_request_details(self, url: str):
        """记录请求的详细信息"""
        mylog.debug(f"Request URL: {url}")
        mylog.debug(f"Request Headers: {self.headers}")
        if self.data:
            mylog.debug(f"Request Data: {self.data}")
        if self.query:
            mylog.debug(f"Request Query Params: {self.query}")


    def send(self) -> requests.Response:
        """发送请求并返回响应"""
        self.load_access_token()  # 加载访问 token
        cookie = self.load_cookie()  # 加载 cookie
        self.host = self.load_environment()  # 加载环境配置中的 host
        url = f"{self.host}{self.path}"  # 构造完整的 URL
        # 设置请求内容类型和数据处理
        self.prepare_data()

        # 调试输出请求头、数据和查询参数
        self.debug_log_request_details(url)
        try:
            # 发送请求
            requests_response = requests.request(
                method=self.method,
                url=url,
                headers=self.headers,
                data=self.data,  # json格式在起前面作了判断
                params=self.query,  # GET 请求时的查询参数
                timeout=self.timeout,
                auth=self.auth,  # 认证信息
                verify=self.verify,
                proxies=self.proxies,  # 代理
                cookies=cookie,
                #allow_redirects=self.allow_redirects  # 是否允许重定向
            )

            # 调试输出响应信息
            mylog.debug(f"Response Status Code: {requests_response.status_code}")
            mylog.debug(f"Response Headers: {requests_response.headers}")

            r = Response(requests_response)
            # 处理响应内容
            return r

        except requests.Timeout:
            mylog.error("Request timed out")
            raise TimeoutError(f"The request timed out after {self.timeout} seconds")
        except requests.RequestException as e:
            mylog.error(f"Request failed: {e}")
            raise SystemExit(f"Request failed: {e}")

# @dataclass
class Response:
    def __init__(self, requests_response: requests.Response):
        """初始化 Response 对象，接收 requests 库的响应对象"""
        self.r = requests_response

    def json(self):
        """返回响应体的 JSON 格式内容"""
        try:
            return self.r.json()  # 解析并返回 JSON 数据
        except ValueError as e:
            # 如果 JSON 解析失败，打印错误并返回 None
            mylog.error(f"Error parsing JSON: {e}")
            return None
    @property
    def status_code(self):
        """返回响应的 HTTP 状态码"""
        return self.r.status_code

    def data(self) -> dict:
        """
        框架规定所有的数据都是字典类型
        """
        return json.loads(base64.decdecode(self.r.text))

# 使用示例
if __name__ == "__main__":
    # 创建一个 GET 请求实例
    req = Request()
    req.type="json"
    req.method = "get"
    req.path = "/posts"
    req.query = {"userId": 1}
    req.host = "https://jsonplaceholder.typicode.com"
    # req = Request(
    #     method="GET",
    #     host="https://jsonplaceholder.typicode.com",
    #     path="/posts",
    #     query={"userId": 1},
    #     headers={},
    #     type="json",
    #     timeout=10  # 设置 10 秒超时
    # )

    try:
        response = req.send()
        print(response.status_code())  # 输出响应内容
    except Exception as e:
        print(f"Error: {e}")

    # 创建一个 POST 请求实例
    post_req = Request(
        method="POST",
        host="https://jsonplaceholder.typicode.com",
        path="/posts",
        data={"title": "foo", "body": "bar", "userId": 1},
        #headers={"Authorization": "Bearer some_token"},
        type="json",
        timeout=5  # 设置 5 秒超时
    )

    try:
        post_response = post_req.send()
        print(post_response.json())  # 输出响应内容
    except Exception as e:
        print(f"Error: {e}")
